home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / x25 / nrs.shar.Z / nrs.shar / output.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-27  |  48.8 KB  |  2,004 lines

  1. # include    "nrs.h"
  2. #define    void_result 0
  3. #ifndef    void_res
  4. #define    void_res int
  5. #endif/*void_res*/
  6.  
  7. # ifndef lint
  8. static char RCSid[]="@(#)$Header: output.c,v 3.6 88/09/08 17:39:37 pb Exp $";
  9. # endif
  10. /***********************************************************************\
  11. *                                     *
  12. * This module does all the output formatting.                *
  13. * Currently it supports                            *
  14. *     york directory format                        *
  15. *     /etc/x25hosts format (UBC X25 code)                *
  16. *     mmdf domain table format                    *
  17. *                                     *
  18. * Fri Jun 28 17:08:17 1985    Julian Onions <jpo@uk.ac.nott.cs>    *
  19. *                                     *
  20. * MMDF output routines rewritten, york2.1 rewritten, york 2.2 added,    *
  21. * text added, VMS added, sendmail added.                *
  22. *                                    *
  23. * Piete Brooks <pb@uk.ac.cam.cl>                    *
  24. *                                    *
  25. * Reading Sendmail format added                        *
  26. *                                     *
  27. * Adrian Pell <A.R.Pell@uk.ac.reading>                    *
  28. *                                     *
  29. * Copyright 1986, Piete Brooks, Julian Onions & Adrian Pell        *
  30. * pb@cl.cam.ac.uk, jpo@hcig.nott.ac.uk, Adrian.R.Pell@reading.ac.uk    *
  31. *                                    *
  32. * This program may be copied as long as you don't remove this notice,    *
  33. * try to make any money off of it, or pretend that you wrote it.    *
  34. *                                     *
  35. * S.E.R.C. Prime textual format added                    *
  36. * Ian Pallfreeman <ian@uk.ac.umist>                    *
  37. *                                     *
  38. * Edinburgh Text format added                        *
  39. * Scott Larnach <scott@uk.ac.ed>                    *
  40. *                                     *
  41. \***********************************************************************/
  42.  
  43. /* ARGSUSED */
  44. /* This is the default format -- i.e. crash out ! */
  45. void_res
  46. noformat(longform, shortform, ap, m3p)
  47. Mod2    *longform;
  48. Mod2    *shortform;
  49. Atomic    *ap;
  50. Mod3    *m3p;
  51. {
  52.     fatal1("No %s output format specified\n",
  53.         (m3p) ? "reverse" : "forward");
  54.     /* NOTREACHED */
  55.     return void_result;    /* keep gcc -Wall happy */
  56. }
  57.  
  58. /* Given a name (from application relay) ensure it's of the right form.
  59.  *
  60.  * Caching: Quickie -- remember last conversion.
  61.  * This will solve double short/long lookup if 1 AP, and also
  62.  * will work wonders for a goup of machines using the same relay ...
  63.  * Currently does 25 lookups and 92 caches -- perfect is 21 and 96 ...
  64.  *
  65.  * pb@cam.cl
  66.  */
  67. static_f char *
  68. longshort_name(name)
  69. char *name;
  70. {    Mod2 *m2, *findm2rec();
  71.     static char *from=NULL, *to=NULL;
  72.  
  73.     if (from && to && !strcmp(name, from))
  74.     {    vprintf2(2, "[Cached    %s -> %s]\n", from, to);
  75.         return to;
  76.     }
  77.     if ( (m2=findm2rec(name)) &&        /* Name exists */
  78.            (m2->ls == longshort ||        /* Already there .. */
  79.         (m2->ls == SHORT && longshort != LONG) ||
  80.          (m2->ls_disp &&        /* or other form exists */
  81.            (m2=getm2rec(m2->ls_disp))))) /* and can be found */
  82.         {    if (from) free(from);
  83.         if (to)   free(to);
  84.         from=strdup(name);
  85.         to=strdup(m2->name);
  86.         vprintf2(2, "[Looked up %s -> %s]\n", name, m2->name);
  87.         return (to) ? to : m2->name;
  88.         }
  89.     vprintf1(2, "[Missed    %s]\n", name);
  90.     return name;
  91. }
  92.  
  93. #ifdef FLIP
  94. #define    noflip(x)    x
  95. char    *flip(str)
  96. char    *str;
  97. {
  98.     static char flipbuf[MAXNAMELEN];
  99.     register char    *dp, *flipp;
  100.     int    i;
  101.  
  102.     flipp = flipbuf;
  103.     for(i = 1, dp = str + strlen(str) - 1; dp > str; dp --)
  104.     {
  105.         if( *dp == '.')
  106.         {
  107.             VOID strncpy(flipp, dp+1, i);
  108.             flipp += i - 1;
  109.             *flipp++ = '.';
  110.             i = 1;
  111.         }
  112.         else    i++;
  113.     }
  114.     VOID strncpy(flipp, dp, i);
  115.     *(flipp + i) = '\0';
  116.     return flipbuf;
  117. }
  118. # endif FLIP
  119.  
  120. # ifdef MULT_OUTPUT_FILES
  121. File_list *findfile(tbl, s, short_name)
  122. File_list *tbl;
  123. int short_name;
  124. char    *s;
  125. {
  126.     if (short_name)
  127.         for(; tbl->dname != 0; tbl++)
  128.         {    int len = strlen(tbl->dname);
  129.             if( tbl->net )
  130.                 continue;
  131.             if( lexequ(s, tbl->dname, len) && len < strlen(s))
  132.                 return tbl;
  133.         }
  134.     else    for(; tbl->ldname != 0; tbl++)
  135.         {    int len = strlen(tbl->ldname);
  136.             if( tbl->net )
  137.                 continue;
  138.             if( lexequ(s, tbl->ldname, len) && len < strlen(s))
  139.                 return tbl;
  140.         }
  141.     return NULL;
  142. }
  143.  
  144. File_list *findnet(tbl, n)
  145. File_list *tbl;
  146. int    n;
  147. {
  148.     for(; tbl->dname != 0; tbl++)
  149.         if( tbl->net == n)
  150.             return tbl;
  151.     return NULL;
  152. }
  153. # endif MULT_OUTPUT_FILES
  154.  
  155. # ifdef    F_YORK
  156. void_res
  157. yorkformat(longform, shortform, ap, m3p)    /* york directory format */
  158. Mod2    *longform;
  159. Mod2    *shortform;
  160. Atomic    *ap;
  161. Mod3    *m3p;
  162. {
  163.     static    headed    = 0;
  164.  
  165.         /*    The name I'm actually interested in    */
  166.     char    *name        = longform->name;
  167.     char    *abbrev        = (shortform) ? shortform->name : name;
  168.         /*    Does it have the default service name ? */
  169.     char    default_name    = 0;
  170.         /*    This is the service string I EXPECT    */
  171.     int    context = (m3p) ? m3p->m3_context : ap->context;
  172.     char    *expected_ybts    = vlookup(context, def_ybstring);
  173.         /*    This is the DTE to use:
  174.          *    EITHER ap->dte for forward
  175.          *    OR     part of text for reverse
  176.          */
  177.     char    *dte = (m3p) ? m3p->m3_dte  : ap->dte;
  178.     char    *ybts= (m3p) ? m3p->m3_ybts : ap->ybts;
  179.         /*    Should there be any YBTS string ?    */
  180.     char    no_ybts        = (ybts && *ybts) ? 0 : 1;
  181.     int    network = (m3p) ? m3p->m3_network : ap->network;
  182.     int    yblen;
  183.         /*    This is a LOCAL COPY of the TS string    */
  184.     char    ybstring[256];
  185.  
  186.     if( headed == 0 && commentfile)
  187.     {
  188.         addcomments(stdout, (m3p) ?
  189.                 "york format reverse NRS table" :
  190.                 "york format NRS table",
  191.                 "Lookup Table");
  192.         headed++;
  193.     }
  194.  
  195.     if (m3p && ! dte)
  196.     {    dte=nullstring;
  197.         if (context == MAIL_NIFTP) return void_result;
  198.     }
  199.  
  200. /*    <isunix>:<network>:<services>:<name>[|abbrev]:<addr>:<comment>    */
  201.     VOID strcpy(ybstring, ybts);
  202.     if (expected_ybts)
  203.     {    /*    Identical ?    */
  204.         if ( strcmp(ybstring, expected_ybts ) == 0)
  205.         {    default_name++;
  206.             no_ybts++;
  207.         }
  208.         /*    Null ybts expected    */
  209.         else if (*expected_ybts == '\0')
  210.             default_name++;
  211.         /*    trailing sub-string ?    */
  212.         else if (yblen = strlen(ybstring))
  213.         {    char *end = ybstring + yblen - strlen(expected_ybts);
  214.  
  215.             /*    NB: If YBTS is of the form
  216.              *        1234/FTP.MAIL
  217.              *    then DONT compress it, as we would generate
  218.              *        1234.FTP.MAIL
  219.              *    from :m:name:000012345678/1234:
  220.              */
  221.             if (end > ybstring &&
  222.                 strcmp(end, expected_ybts) == 0 &&
  223.                 end[-1] == '.')
  224.             {    default_name++;
  225.                 end[-1] = '\0';
  226.             }
  227.         }
  228.     }
  229.     /*    If no ybts, but none expected, then use explicit ! */
  230.     else if ( expected_ybts && *expected_ybts == '\0')
  231.         default_name++;
  232.  
  233.     {    char * net = vlookup(network, netnames);
  234.         char *cont = (context == DESC) ? nullstring :
  235.             vlookup(context, default_name ? imp_services:
  236.                 exp_services);
  237.         if (!net)
  238.         {    warn2(1, "%10s: net 0x%02x unknown",
  239.                 name, network);
  240.             net = "??";
  241.         }
  242.         if (!cont)
  243.         {    warn2(1, "%10s: context 0x%02x unknown",
  244.                 name, context);
  245.             cont = "??";
  246.         }
  247.         printf("0:%s:%s%s%s:%s", net,
  248.             (m3p) ? "|" : "", cont, (m3p) ? "" : "|", name);
  249.     }
  250.  
  251.     if (strcmp(name, abbrev))
  252.         printf("|%s", abbrev);
  253.     printf(":");
  254.  
  255.     /*    Prefix with gateway if needed  .... */
  256.     if(network == PSS   && pssgateway)    printf("%s", pssgateway);
  257.     if(network == JANET && janetgateway)    printf("%s", janetgateway);
  258.  
  259.     /*    The DTE ....    */
  260.     printf("%s", dte);
  261.     /*    Plus YBTS    */
  262.     if( ! no_ybts )
  263.     {    char * colon;
  264.         while (colon = index(ybstring, ':')) *colon = COLON;
  265.         printf("/%s", ybstring);
  266.     }
  267.     printf(":");
  268.  
  269.     /*    The prefix which was stripped */
  270.     printf(":");
  271.  
  272.     /*    The extra values    */
  273.     if( !m3p && ap->n_relays > 0 )
  274.     {    int relay;
  275.         char * cont = vlookup(ap->context, exp_services);
  276.         if (!cont)
  277.         {    warn2(1, "%10s: context 0x%02x unknown",
  278.                 name, ap->context);
  279.             cont = "?";
  280.         }
  281.         printf("ar%s=", cont);
  282.         for (relay=0; relay < ap->n_relays; relay++)
  283.         {    char * colon = ap->ar[relay];
  284.             while (colon = index(colon, ':')) *colon++ = COLON;
  285.             printf("%s%s", (relay==0) ? "" : ",", ap->ar[relay]);
  286.         }
  287.     }
  288.     printf(":");
  289.  
  290.     if( !m3p && ap->n_descs > 0 )
  291.     {    int desc;
  292.         for (desc=0; desc < ap->n_descs; desc++)
  293.             printf("%s%s", (desc==0) ? "" : "|", ap->desc[desc]);
  294.     }
  295.     /*    The comment        */
  296.     printf("\n");
  297.  
  298.     if (m3p && ap && dte != ap->dte && ap->dte && strcmp(dte, ap->dte))
  299.         warn3(1, "%-18s DTE is %-14s rather than %-14s",
  300.             name, dte, ap->dte);
  301.     return void_result;
  302. }
  303.  
  304. # endif F_YORK
  305.  
  306. # ifdef    F_X25HOSTS
  307. /* ARGSUSED */
  308. void_res
  309. x25hostsformat(longform, shortform, ap, m3p) /* etc/x25hosts format */
  310. Mod2    *longform;
  311. Mod2    *shortform;
  312. Atomic    *ap;
  313. Mod3    *m3p;
  314. {
  315.     static headed = 0;
  316.  
  317.     if (!ap)
  318.     {    warn0(1, "X25HOSTS passed reverse object");
  319.         return void_result;
  320.     }
  321.  
  322.     if(ap->n_relays > 0 || (ap->ybts && *ap->ybts) )
  323.         return void_result;
  324.  
  325.     if ( ! shortform)
  326.         shortform = longform;
  327.     if( headed == 0 && commentfile)
  328.     {
  329.         addcomments(stdout, "x25hosts NRS tables", "Lookup Table");
  330.         headed++;
  331.     }
  332.  
  333.     printf("%-14s ", ap->dte);
  334.     if(stripoff && lexequ(stripoff, shortform->name, strlen(stripoff)) )
  335.         printf("%-19s ", shortform->name + strlen(stripoff));
  336.     printf("%-19s ", shortform->name);
  337.     if( ! lexequ(shortform->name, longform->name, strlen(longform->name)))
  338.     {
  339.         if(stripoff && lexequ(stripoff, longform->name, strlen(stripoff)) )
  340.             printf("%-19s ", longform->name + strlen(stripoff));
  341.         printf(" %s", longform->name);
  342.     }
  343.     putchar('\n');
  344.     return void_result;
  345. }
  346. # endif    F_X25HOSTS
  347.  
  348. # ifdef    F_MMDF
  349. /* ARGSUSED */
  350. void_res
  351. mmdfformat(longform, shortform, ap, m3p)    /* mmdf domain table format */
  352. Mod2    *longform;
  353. Mod2    *shortform;
  354. Atomic    *ap;
  355. Mod3    *m3p;
  356. {
  357.     File_list    *filep;
  358.     FILE    *fp;
  359.     char    *flip();
  360.     int    i;
  361.     char    *name1, *name2, *dmn1;
  362.  
  363.     if (!ap)
  364.     {    warn0(1, "MMDF passed reverse object");
  365.         return void_result;
  366.     }
  367.  
  368.     if ( ! shortform)
  369.         shortform = longform;
  370.  
  371.     if( longshort == LONG )    /* output in short = alias of long */
  372.         name1 = longform->name,  name2 = shortform->name;
  373.     else    name1 = shortform->name, name2 = longform->name;
  374.  
  375.     if((filep = findfile(fil_list, name1, longshort != LONG)) == NULL)
  376.     {    warn1(1, "can't find a place for %s", name1);
  377.         return void_result;
  378.     }
  379.  
  380.     if( longshort == LONG )    /* output in short = alias of long */
  381.         dmn1 = filep->ldname;
  382.     else    dmn1 = filep->dname;
  383.  
  384.     fp = getfp(filep->fname, "w");
  385.     if( (filep->flags & USED) == 0 && commentfile)
  386.     {
  387.         addcomments(fp, filep->fname, "Domain Table");
  388.         filep->flags |= USED;
  389.     }
  390.  
  391.     fprintf(fp, "%s:", flip(name1 + strlen(dmn1)));
  392.     fprintf(fp, "%s", flip(name1));
  393.     if(! (filep->flags & LOCAL))    /* not a local domain */
  394.     {    if (relay_host)        /* and we have a relay point*/
  395.             fprintf(fp, " %s", relay_host);
  396.         /* else dump the AR */
  397.         else for( i = 0; i < ap->n_relays; i++)
  398.             fprintf(fp, " %s", flip(longshort_name(ap->ar[i])));
  399.     }
  400.     putc('\n', fp);
  401. /* compare two forms - if there the same skip - take care to compare
  402.    the two forms without dmns on. e.g. uk.ac.shtdmn.cs &&
  403.    uk.ac.longishdmn.cs are the same if in longishdmn */
  404.  
  405.     if((filep = findfile(fil_list, name2, longshort == LONG)) == NULL)
  406.             warn2(1, "can't find a place for other form of %s (%s)",
  407.                                 name1, name2);
  408.     else
  409.     {   char *dmn2;
  410.         if( longshort != LONG )    /* output in short = alias of long */
  411.             dmn2 = filep->ldname;
  412.         else    dmn2 = filep->dname;
  413.  
  414.         if( ! lexequ(name1 + strlen(dmn1), name2 + strlen(dmn2),
  415.             strlen(longform->name) - strlen(filep->ldname)))
  416.         {    fp = getfp(filep->fname, "w");
  417.         if( (filep->flags & USED) == 0 && commentfile)
  418.         {
  419.             addcomments(fp, filep->fname, "Domain Table");
  420.             filep->flags |= USED;
  421.         }
  422.         fprintf(fp, "%s:", flip(name2 + strlen(dmn2)));
  423.         fprintf(fp, "%s",  flip(name1));
  424.         if (! (filep->flags & LOCAL))    /* not a local domain */
  425.         {    if (relay_host)        /* and we have a relay point*/
  426.                 fprintf(fp, " %s", relay_host);
  427.             /* else dump the AR */
  428.             else for( i = 0; i < ap->n_relays; i++)
  429.               fprintf(fp, " %s", flip(longshort_name(ap->ar[i])));
  430.         }
  431.         putc('\n', fp);
  432.         }
  433.     }
  434.  
  435.     /* It isn't local, then if App Relay or relay_host, no chan needed */
  436.     if(! (filep->flags & LOCAL))    /* not a local domain */
  437.         if (relay_host || ap->n_relays > 0)    return void_result;
  438.  
  439.     if((filep = findnet(fil_list, ap->network)) == NULL)
  440.         return void_result;
  441.     fp = getfp(filep->fname, "w");
  442.     if( (filep->flags & USED) == 0 && commentfile)
  443.     {
  444.         addcomments(fp, filep->fname, "Channel Table");
  445.         filep->flags |= USED;
  446.     }
  447.     fprintf( fp, "%s:", flip(name1));
  448.     if( *filep->dname && lexequ(filep->dname, name1, i = strlen(filep->dname)))
  449.         fprintf(fp, "%s\n", name1 + i );
  450.     else    fprintf(fp, "%s\n", name1);
  451.  
  452. #ifdef    MMDF_CHAN_BOTH_FORMS
  453.     /* It has been reported that mmdf does not need chanel tables for both
  454.      * the long & short, as only one should be generated by the domain
  455.      * tables.  However, some sites aren't very strict about that ...
  456.      */
  457.     if(lexequ(name1, name2, strlen(longform->name)) )
  458.         return void_result;
  459.  
  460.     fprintf( fp, "%s:", flip(name2));
  461.     if( *filep->dname && lexequ(filep->dname, name2, i = strlen(filep->dname)))
  462.         fprintf(fp, "%s\n", name2 + i );
  463.     else    fprintf(fp, "%s\n", name2);
  464. #endif    MMDF_CHAN_BOTH_FORMS
  465.     return    void_result;
  466. }
  467.  
  468. void_res
  469. mmdfdomain(dp)
  470. Domain    *dp;
  471. {    static char name1[] = "-top.dmn-...";
  472.     File_list    *filep;
  473.     FILE    *fp;
  474.     char    *flip();
  475.  
  476.     if((filep = findfile(fil_list, name1, 1)) == NULL)
  477.     {    warn1(1, "can't find a place for %s", name1);
  478.         return void_result;
  479.     }
  480.  
  481.     fp = getfp(filep->fname, "w");
  482.     if( (filep->flags & USED) == 0 && commentfile)
  483.     {
  484.         addcomments(fp, filep->fname, "Top Domain Table");
  485.         filep->flags |= USED;
  486.     }
  487.  
  488.     fprintf(fp, "%s:", flip(dp->name));
  489.     fprintf(fp, "%s\n", flip(longshort_name(dp->gateway)));
  490.  
  491.     return void_result;
  492. }
  493. # endif    F_MMDF
  494.  
  495. #ifdef    F_TEXT
  496. void_res
  497. textformat(longname, shortname, ap, m3p)
  498. Mod2    *longname, *shortname;
  499. Atomic    *ap;
  500. Mod3    *m3p;
  501. {
  502.     if (m3p) printf("Calling address %s\n",  m3p->m3_string);
  503.     if (longshort == LONG || !shortname)
  504.         printf("Standard name     %s\n", longname->name);
  505.     if (longshort != LONG && shortname)
  506.         printf("Abbreviated name  %s\n", shortname->name);
  507.     if (!m3p) {
  508.         if (ap->dte  && *ap->dte)
  509.             printf("DTE                %s\n", ap->dte);
  510.         if (ap->ybts && *ap->ybts)
  511.             printf("YB String          %s\n", ap->ybts);
  512.         {    int i;
  513.             for (i=0; i< ap->n_relays; i++)
  514.                 printf("Application Relay %s\n", ap->ar[i]);
  515.             for (i=0; i< ap->n_descs; i++)
  516.                 printf("Description       %s\n", ap->desc[i]);
  517.         }
  518.     }
  519.     else {
  520.         if (m3p->m3_dte)
  521.             printf("DTE                %s\n", m3p->m3_dte);
  522.         if (*(m3p->m3_ybts))
  523.             printf("YB String          %s\n", m3p->m3_ybts);
  524.         {    int i;
  525.             for (i=0; i< ap->n_descs; i++)
  526.                 printf("Description       %s\n", ap->desc[i]);
  527.         }
  528.     }
  529.     printf("\n");
  530.     return void_result;
  531. }
  532. #endif    F_TEXT
  533.  
  534. #ifdef    F_VMS4
  535. #define    max_name_len    32
  536. /* Thee is no way to represent an applicatio relay, so do not generate it */
  537. #define    has_relay()    (! m3p && ap->n_relays && !ignore_relay)
  538.  
  539. char *
  540. vms4_quote(name)
  541. char *name;
  542. {    static char buff[1024];
  543.     if (!index(name, '-'))    return name;
  544.     VOID sprintf(buff, "\"%s\"", name);
  545.     return buff;
  546. }
  547.  
  548. /* ARGSUSED */
  549. void_res
  550. vms4_single(m2p, ap, m3p, skip)
  551. int skip;
  552. Mod2    *m2p;
  553. Atomic    *ap;
  554. Mod3    *m3p;
  555. {    char    *quote="";
  556.     char    *dte = (m3p) ? m3p->m3_dte  : ap->dte;
  557.     char    *ybts= (m3p) ? m3p->m3_ybts : ap->ybts;
  558.     int    context = (m3p) ? m3p->m3_context : ap->context;
  559.     char    no_ybts = ybts == NULL || !strcmp(ybts, "");
  560.  
  561.     if (m3p && ! dte)
  562.     {    dte=nullstring;
  563.         if (context == MAIL_NIFTP) return void_result;
  564.     }
  565.     if (has_relay())    return void_result;  /* no relay -> ignore */
  566.  
  567.     if (!no_ybts && (index(ybts, '-') || index(ybts, '+')))
  568.         quote = "\"";
  569.     {    char *cont = vlookup(context, vms4_services);
  570.         if (!cont)
  571.         {    warn2(1, "%10s: context 0x%02x unknown",
  572.                 dte, context);
  573.             cont = "??";
  574.         }
  575.  
  576.         printf("+%s=%s%s", cont, quote, dte+skip);
  577.     }
  578.     if (!no_ybts)    printf(".%s%s", ybts, quote);
  579. #ifdef notdef
  580.     if (! m3p)
  581.     {    int i;
  582.         for (i=0; i< ap->n_relays; i++)
  583.             printf(" AR=\"%s\"", ap->ar[i]);
  584.     }
  585. #endif notdef
  586.     return void_result;
  587. }
  588.  
  589. void_res
  590. vms4_process(m2p, m3p, m4p)
  591. Mod2    *m2p;
  592. Mod3    *m3p;
  593. Mod4    *m4p;
  594. {    int j;
  595.     int some = 0;
  596.     int slow = 0;
  597.     int noybts = -1;
  598.     int skip = 0;    /* Keep gcc -Wall happy */
  599.     char dte[15];
  600.  
  601.     if (strlen(m2p->name) > 32)    return 1;
  602.  
  603.     for( j = 0; j < m4p->nquads; j++)
  604.         if (m4p->quads[j].fnumb <= max_fnumb)
  605.         {    Atomic    *ap;
  606.         if(( ap = getatrec(&(m4p->quads[j]), m2p)) == NULL)
  607.             continue;
  608.         if (has_relay())    continue;    /* relay -> ignore */
  609.  
  610.         if (!some++)
  611.         {    VOID strcpy(dte, ap->dte);
  612.             skip = strlen(dte);
  613.         }
  614.         while (strncmp(dte, ap->dte, skip))
  615.             skip--, noybts = -1;
  616.         if (!ap->ybts || !*ap->ybts)
  617.             if (noybts>=0)    skip--, noybts = -1;
  618.             else        noybts = j;
  619.         }
  620.     if (!some)    return 1;
  621.  
  622.     printf("D %s\n", vms4_quote(m2p->name));
  623.     printf("A %s", vms4_quote(m2p->name));
  624.     if (slow)
  625.     {    printf("\n");
  626.         return 0;
  627.     }
  628.  
  629.     if (skip)    printf("+=%.*s", skip, dte);
  630.  
  631.     for(j = 0; j < m4p->nquads; j++)
  632.         if (j != noybts && m4p->quads[j].fnumb <= max_fnumb)
  633.         {    Atomic    *ap;
  634.         if(( ap = getatrec(&(m4p->quads[j]), m2p)) == NULL)
  635.             continue;
  636.         vms4_single(m2p, ap, m3p, skip);
  637.         }
  638.     if (noybts >= 0) vms4_single(m2p, getatrec(&(m4p->quads[noybts]), m2p),
  639.                 m3p, skip);
  640.     printf("\n");
  641.     return 1;
  642. }
  643.  
  644. void_res
  645. vms4m4rec(m4p, shortname, longname, m3p)
  646. Mod4    *m4p;
  647. Mod3    *m3p;
  648. Mod2    *shortname;
  649. Mod2    *longname;
  650. {
  651.     static    headed = 0;
  652.  
  653.     if (!m4p || m3p)
  654.     {    warn1(1, "VMS4 passed reverse object (%s)",
  655.             (m3p) ? "m3p" : "!m4p");
  656.         return 1;
  657.     }
  658.  
  659.     if( headed == 0 && commentfile)
  660.     {    addcomments(stdout, "VMS4 format table", "Lookup Table");
  661.         headed++;
  662.     }
  663.  
  664.     if (shortname) {
  665.         if (!vms4_process(shortname, m3p, m4p))    return 0;
  666.         if(!lexequ(shortname->name, longname->name, strlen(longname->name)))
  667.             if (!vms4_process(longname, m3p, m4p)) return 0;
  668.     }
  669.     else
  670.         if (!vms4_process(longname, m3p, m4p)) return 0;
  671.     return 1;
  672. }
  673.  
  674. #ifdef    EVER_WANTED
  675. void_res
  676. vms4format(longname, shortname, ap, m3p)
  677. Mod2    *longname, *shortname;
  678. Atomic    *ap;
  679. Mod3    *m3p;
  680. {
  681.     char    *dte = (m3p) ? m3p->m3_dte  : ap->dte;
  682.     char    *ybts= (m3p) ? m3p->m3_ybts : ap->ybts;
  683.     int    context = (m3p) ? m3p->m3_context : ap->context;
  684.     char    no_ybts = ybts == NULL || !strcmp(ybts, "");
  685.  
  686.     if (m3p && ! dte)
  687.     { dte=nullstring; if (context == MAIL_NIFTP) return void_result; }
  688.  
  689.     if (strlen(longname->name) < max_name_len)
  690.         printf("M %s", vms4_quote(longname->name));
  691.     {    char *cont = vlookup(context, vms4_services);
  692.         if (!cont)
  693.         {    warn2(1, "%10s: context 0x%02x unknown", dte, context);
  694.             cont = "??";
  695.         }
  696.  
  697.         printf("+%s=%s", cont, dte);
  698.     }
  699.     if (!no_ybts)    printf(".%s", ybts);
  700.     if(shortname && !lexequ(shortname->name, longname->name, strlen(longname->name)))
  701.     {    printf("M %s", vms4_quote(shortname->name));
  702.         {    char *cont = vlookup(context, vms4_services);
  703.             if (!cont)
  704.             {    warn2(1, "%10s: context 0x%02x unknown",
  705.                     dte, context);
  706.                 cont = "??";
  707.             }
  708.  
  709.             printf("+%s=%s", cont, dte);
  710.         }
  711.         if (!no_ybts)    printf(".%s", ybts);
  712.     }
  713.     if (! m3p)
  714.     {    int i;
  715.         for (i=0; i< ap->n_relays; i++)
  716.             printf(" AR=\"%s\"", ap->ar[i]);
  717.     }
  718.     printf("\n");
  719.     return void_result;
  720. }
  721. #endif    EVER_WANTED
  722. #endif    F_VMS4
  723.  
  724. #ifdef    F_VMS5
  725. /* Thee is no way to represent an applicatio relay, so do not generate it */
  726. #define    has_relay()    (! m3p && ap->n_relays && !ignore_relay)
  727. #define    MAXVMS5CONTEXTS    (JTMP+1)
  728. #define    MAXVMS5NETWORKS    (JANET+1)
  729.  
  730. int vms5_context_interested[] = { TS29, X29, NIFTP, MAIL_NIFTP, JTMP };
  731. int vms5_net_interested[] = { JANET, PSS };
  732.  
  733. static_f char *
  734. vms5_quote(name)
  735. char *name;
  736. {    static char buff[1024];
  737.     if (!index(name, '-'))    return name;
  738.     VOID sprintf(buff, "\"%s\"", name);
  739.     return buff;
  740. }
  741.  
  742. /* ARGSUSED */
  743. static_f void_res
  744. vms5_single(m2p, ap, m3p, skip)
  745. int skip;
  746. Mod2    *m2p;
  747. Atomic    *ap;
  748. Mod3    *m3p;
  749. {    char    *dte = (m3p) ? m3p->m3_dte  : ap->dte;
  750.     char    *ybts= (m3p) ? m3p->m3_ybts : ap->ybts;
  751.     int    context = (m3p) ? m3p->m3_context : ap->context;
  752.     char    no_ybts = ybts == NULL || !strcmp(ybts, "");
  753.     char    *cont;
  754.  
  755.     if (m3p && ! dte)
  756.     {    dte=nullstring;
  757.         if (context == MAIL_NIFTP) return void_result;
  758.     }
  759.     if (has_relay())    return void_result;  /* no relay -> ignore */
  760.  
  761.     cont = vlookup(context, vms5_services);
  762.     if (!cont)
  763.     {    warn2(1, "%10s: context 0x%02x unknown",
  764.             dte, context);
  765.         cont = "??";
  766.     }
  767.     printf("\"%s=%s", cont, dte+skip);
  768.     if (!no_ybts)    printf(".%s", ybts);
  769.     printf("\"");
  770.     printf(",");
  771.  
  772. #ifdef notdef
  773.     if (! m3p)
  774.     {    int i;
  775.         for (i=0; i< ap->n_relays; i++)
  776.             printf(" AR=\"%s\"", ap->ar[i]);
  777.     }
  778. #endif notdef
  779.     return void_result;
  780. }
  781.  
  782. static_f void_res
  783. vms5_process(longname, shortname, m3p, m4p)
  784. Mod2    *longname;
  785. Mod2    *shortname;
  786. Mod3    *m3p;
  787. Mod4    *m4p;
  788. {    register i, j;
  789.     int nets = 0;
  790.     int where[MAXVMS5CONTEXTS][MAXVMS5NETWORKS];
  791.     int got[MAXVMS5NETWORKS];
  792.     register Table *tp;
  793.  
  794.     /* Initialise the tables .. */
  795.     for (j=0; j<MAXVMS5NETWORKS; j++)
  796.     {    got[j] = 0;
  797.         for (i=0; i<MAXVMS5CONTEXTS; i++) where[i][j] = -1;
  798.     }
  799.     
  800.     /* Fill in what we have */
  801.     for(j = 0; j < m4p->nquads; j++)
  802.         if (m4p->quads[j].fnumb <= max_fnumb &&
  803.             (tp = gettab(m4p->quads[j].fnumb)) &&
  804.             tp->T_context < MAXVMS5CONTEXTS &&
  805.             tp->T_network < MAXVMS5NETWORKS)
  806.             where[tp->T_context][tp->T_network] = j;
  807.  
  808.     for (i=0; i < sizeof vms5_net_interested / sizeof vms5_net_interested[0]; i++)
  809.     {    int net = vms5_net_interested[i];
  810.         for(j = 0;
  811.         j < sizeof vms5_context_interested / sizeof vms5_context_interested[0];
  812.             j++)
  813.             if(where[vms5_context_interested[j]][net] >= 0) got[net]++;
  814.     }
  815.  
  816.     /* Count the number of nets */
  817.     for (j=0; j<MAXVMS5NETWORKS; j++) if (got[j]) nets++;
  818.  
  819.     printf("D S %s\n", vms5_quote(longname->name));
  820.     if(shortname && !lexequ(shortname->name, longname->name, strlen(longname->name)))
  821.         printf("D A %s\n", vms5_quote(shortname->name));
  822.  
  823.     /* Print info for nets that have some info */
  824.     for (i=0; i < (sizeof vms5_net_interested / sizeof vms5_net_interested[0]); i++)
  825.         if (got[vms5_net_interested[i]])
  826.         {    int net = vms5_net_interested[i];
  827.         char *netname = vlookup(net, netnames);
  828.         int skip = 0;   /* Keep gcc -Wall happy */
  829.         char dte[15];
  830.         int some = 0;
  831.  
  832.         for(j = 0;
  833.         j < (sizeof vms5_context_interested / sizeof vms5_context_interested[0])-1;
  834.             j++)
  835.             if (m4p->quads[where[vms5_context_interested[j]][net]].fnumb <= max_fnumb)
  836.             {    Atomic    *ap;
  837.             if(( ap = getatrec(&(m4p->quads[where[vms5_context_interested[j]][net]]), longname)) == NULL)
  838.                 continue;
  839.             if (has_relay())    continue;    /* relay -> ignore */
  840.  
  841.             if (!some++)
  842.             {    VOID strcpy(dte, ap->dte);
  843.                 skip = strlen(dte);
  844.             }
  845.             while (strncmp(dte, ap->dte, skip)) skip--;
  846.             }
  847.         if (!some)    continue;
  848.  
  849.         printf("A S %s %s ", vms5_quote(longname->name), netname);
  850. fflush(stdout);
  851.         if(shortname && !lexequ(shortname->name, longname->name, strlen(longname->name)))
  852.             printf("/ALIAS=(\"%s\")", shortname->name);
  853.         printf("/FAST_SELECT ");
  854.         printf("\"%.*s\" ", skip, dte);
  855. fflush(stdout);
  856.  
  857.         /* Now the quads themselves */
  858.         for(j = 0;
  859.         j < (sizeof vms5_context_interested / sizeof vms5_context_interested[0])-1;
  860.             j++)
  861.         {    Atomic  *ap;
  862.  
  863. vprintf2(2, "[try %d -> %d]\n", j, where[vms5_context_interested[j]][net]);
  864.                     if(!(ap=getatrec(&(m4p->quads[
  865.                     where[vms5_context_interested[j]][net]
  866.                     ]), shortname)))
  867.                             continue;
  868.             vprintf2(2, "[%d -> %x]\n", j, ap);
  869.             vms5_single(shortname, ap, m3p, skip);
  870.         }
  871.         printf("\n");
  872.         }
  873.     return 1;
  874. }
  875.  
  876. void_res
  877. vms5m4rec(m4p, shortname, longname, m3p)
  878. Mod4    *m4p;
  879. Mod3    *m3p;
  880. Mod2    *shortname;
  881. Mod2    *longname;
  882. {
  883.     static    headed = 0;
  884.  
  885.     if (!m4p || m3p)
  886.     {    warn1(1, "VMS5 passed reverse object (%s)",
  887.             (m3p) ? "m3p" : "!m4p");
  888.         return 1;
  889.     }
  890.  
  891.     if( headed == 0 && commentfile)
  892.     {    addcomments(stdout, "VMS5 format table", "Lookup Table");
  893.         headed++;
  894.     }
  895.  
  896.     if (!vms5_process(longname, shortname, m3p, m4p))    return 0;
  897.     return 1;
  898. }
  899.  
  900. #endif    F_VMS5
  901.  
  902. #ifdef    F_SMAIL
  903. void_res
  904. smailformat(longname, shortname, ap, m3p)
  905. Mod2    *longname, *shortname;
  906. Atomic    *ap;
  907. Mod3    *m3p;
  908. {
  909.     if (!m3p) {
  910.         printf("%s ", longname->name);
  911.         switch(ap->network) {
  912.         case PSS:
  913.             printf("pss,");
  914.             break;
  915.         
  916.         case JANET:
  917.             printf("janet,");
  918.             break;
  919.         }
  920.         
  921.         if (ap->dte && *ap->dte) printf("%s", ap->dte);
  922.         if (ap->ybts && *ap->ybts)
  923.             printf("/%s", ap->ybts);
  924.         {    int i;
  925.             for (i=0; i< ap->n_relays; i++)
  926.                 printf("%s%s", i==0?",":"%", ap->ar[i]);
  927.         }
  928.         printf("\n");
  929.         if (shortname && !lexequ(shortname->name, longname->name, strlen(longname->name))) {
  930.             printf("%s ", shortname->name);
  931.             switch(ap->network) {
  932.             case PSS:
  933.                 printf("pss,");
  934.                 if (pssgateway)
  935.                     printf("%s", pssgateway);
  936.                 break;
  937.             
  938.             case JANET:
  939.                 printf("janet,");
  940.                 if (janetgateway)
  941.                     printf("%s", janetgateway);
  942.                 break;
  943.             }
  944.             
  945.             if (ap->dte  && *ap->dte) printf("%s", ap->dte);
  946.             if (ap->ybts && *ap->ybts)
  947.                 printf("/%s", ap->ybts);
  948.             {    int i;
  949.                 for (i=0; i< ap->n_relays; i++)
  950.                     printf("%s%s", i==0?",":"%", ap->ar[i]);
  951.             }
  952.             printf("\n");
  953.         }
  954.     }
  955.     else {
  956.         printf("%s %s\n", m3p->m3_string, longname->name);
  957.     }
  958.     return void_result;
  959. }
  960. #endif    F_SMAIL
  961.  
  962. #ifdef    F_SENDMAIL
  963. /* Generate uk.dom, abbrev.dom */
  964.  
  965. /* ARGSUSED */
  966. void_res
  967. sendmailformat(longname, shortname, ap, m3p)    /* sendmail domain table format */
  968. Mod2    *longname;
  969. Mod2    *shortname;
  970. Atomic    *ap;
  971. Mod3    *m3p;
  972. {
  973.     File_list    *filep;
  974.     FILE    *fp;
  975.     char    *name1, *name2, *dmn1, *dmn2;
  976.     int    strip_len1=0, strip_len2=0;
  977.     char    end_name1[100], end_name2[100];
  978.     char    *dot;
  979.     static    char    lastname[1024] = { '\0' };
  980.     static    char    lastabbrev[1024] = { '\0' };
  981.     static    char    lastrname[1024] = { '\0' };
  982.     static    char    lastrelay[1024] = { '\0' };
  983.     char    *flip();
  984.  
  985.     if (!ap)
  986.     {    warn0(1, "SENDMAIL passed reverse object");
  987.         return void_result;
  988.     }
  989.  
  990.     if (! shortname) shortname = longname;
  991.     
  992.     if( longshort == LONG )    /* output in short = alias of long */
  993.         name1 = longname->name,  name2 = shortname->name;
  994.     else    name1 = shortname->name, name2 = longname->name;
  995.  
  996.     if (!lexequ(name1, name2, strlen(name1)) && strcmp(lastabbrev, name2))
  997.     {    File_list    *filep;
  998.         if((filep = findfile(fil_list, "-abbrev.dom-...", 1)) == NULL)
  999.         {    static int warned = 0;
  1000.             if (warned == 0)
  1001.             {    warn0(1, "can't find a place for abbreviations");
  1002.                 warned++;
  1003.             }
  1004.         }
  1005.         else
  1006.         {    fp = getfp(filep->fname, "w");
  1007.             if( (filep->flags & USED) == 0 && commentfile)
  1008.             {    addcomments(fp, filep->fname, "Abbreviation Table");
  1009.                 filep->flags |= USED;
  1010.             }
  1011.             fprintf(fp, "%-20s", flip(name2));
  1012.             fprintf(fp, " %s\n", flip(name1));
  1013.         }
  1014.         strcpy(lastabbrev, name2);
  1015.     }
  1016.  
  1017.     filep = findfile(fil_list, name1, longshort != LONG);
  1018.  
  1019.     /* relays and not a local domain */
  1020.     if(ap->n_relays > 0 && ! (filep && (filep->flags & LOCAL)) &&
  1021.         (strcmp(lastrname, name1) || strcmp(lastrelay, ap->ar[0]) ||
  1022.          ap->n_relays > 1))
  1023.     {    File_list    *filep;
  1024.         if((filep = findnet(fil_list, ap->network)) == NULL)
  1025.         {    static int warned = 0;
  1026.             if (warned++ == 0)
  1027.                 warn0(1, "can't find a place for channel info");
  1028.         }
  1029.         else
  1030.         {    int i;
  1031.             fp = getfp(filep->fname, "w");
  1032.             if( (filep->flags & USED) == 0 && commentfile)
  1033.             {    addcomments(fp, filep->fname, "Channel Table");
  1034.                 filep->flags |= USED;
  1035.             }
  1036.             fprintf(fp, "%-20s", noflip(name1));
  1037.             for( i = 0; i < ap->n_relays; i++) /* dump the AR */
  1038.                 fprintf(fp, " %s",
  1039.                     noflip(longshort_name(ap->ar[i])));
  1040.             fprintf(fp, "\n");
  1041.  
  1042.             /* Other style name ? */
  1043.             if( (strlen(name1) != strlen(name2)) ||
  1044.                 ! lexequ(name1, name2, strlen(name1)))
  1045.             {    fprintf(fp,"%-20s", noflip(name2));
  1046.                 for( i = 0; i < ap->n_relays; i++)
  1047.                     fprintf(fp, " %s",
  1048.                        noflip(longshort_name(ap->ar[i])));
  1049.                 fprintf(fp, "\n");
  1050.  
  1051.             }
  1052.         }
  1053.         strcpy(lastrname, name1);
  1054.         strcpy(lastrelay, ap->ar[0]);
  1055.     }
  1056.  
  1057.     if(filep == NULL)
  1058.     {    warn1(1, "can't find a place for %s", name1);
  1059.         return void_result;
  1060.     }
  1061.  
  1062.     fp = getfp(filep->fname, "w");
  1063.     if( (filep->flags & USED) == 0 && commentfile)
  1064.     {    addcomments(fp, filep->fname, "Domain Table");
  1065.         filep->flags |= USED;
  1066.     }
  1067.     
  1068.     if( longshort == LONG )    /* output in short = alias of long */
  1069.         { dmn1 = filep->ldname; dmn2 = filep->dname; }
  1070.     else    { dmn1 = filep->dname; dmn2 = filep->ldname; }
  1071.  
  1072.     strcpy(end_name1, name1 +strlen(dmn1));    /* name within domain */
  1073.  
  1074.  
  1075.     if (dot = index(end_name1, '.'))
  1076.     {    strip_len1 = strlen(dot); *dot = '\0'; } /* single level of */
  1077.  
  1078.     /* cheapo check for a repeat of the last domain */
  1079.     if (strcmp(end_name1, lastname) == 0)    return void_result;
  1080.  
  1081.     VOID strcpy(lastname, end_name1);
  1082.     
  1083.     fprintf(fp, "%-20s", flip(end_name1));
  1084.     fprintf(fp, " %s", flip(name1) + strip_len1);
  1085.     putc('\n', fp);
  1086.  
  1087.     if((filep = findfile(fil_list, name2, longshort == LONG)) == NULL)
  1088.     {    warn1(1, "can't find a place for %s", name1);
  1089.         return void_result;
  1090.     }
  1091.  
  1092.     strcpy(end_name2, name2 +strlen(dmn2));    /* other one */
  1093.     if (dot = index(end_name2, '.'))         /* domain only ... */
  1094.     {    strip_len2 = strlen(dot); *dot = '\0'; }
  1095.  
  1096.     /* Other style name ? */
  1097.     if( (strlen(end_name1) != strlen(end_name2)) ||
  1098.         ! lexequ(end_name1, end_name2, strlen(end_name1)))
  1099.     {
  1100.         fp = getfp(filep->fname, "w");
  1101.         if( (filep->flags & USED) == 0 && commentfile)
  1102.         {
  1103.             addcomments(fp, filep->fname, "Domain Table");
  1104.             filep->flags |= USED;
  1105.         }
  1106.         fprintf(fp,"%-20s", flip(end_name2));
  1107.         fprintf(fp, " %s\n", flip(name2) + strip_len2);
  1108.     }
  1109.     return void_result;
  1110. }
  1111.  
  1112. void_res
  1113.  
  1114. sendmaildomain(dp)
  1115. Domain    *dp;
  1116. {    static char name1[] = "-top.dom-...";
  1117.     File_list    *filep;
  1118.     FILE    *fp;
  1119.     char    *flip();
  1120.  
  1121.     if((filep = findfile(fil_list, name1, 1)) == NULL)
  1122.     {    warn1(1, "can't find a place for %s", name1);
  1123.         return void_result;
  1124.     }
  1125.  
  1126.     fp = getfp(filep->fname, "w");
  1127.     if( (filep->flags & USED) == 0 && commentfile)
  1128.     {
  1129.         addcomments(fp, filep->fname, "Top Domain Table");
  1130.         filep->flags |= USED;
  1131.     }
  1132.  
  1133.     fprintf(fp, "%-20s", flip(dp->name));
  1134.     fprintf(fp, " %s\n", flip(longshort_name(dp->gateway)));
  1135.  
  1136.     return void_result;
  1137. }
  1138. #endif    F_SENDMAIL
  1139.  
  1140. # ifdef    F_YORK21
  1141. static_f void_res
  1142. york_21format(m2p, ap, m3p) /* york D2.1 directory format */
  1143. Mod2    *m2p;
  1144. Atomic    *ap;
  1145. Mod3    *m3p;
  1146. {    char    *name = m2p->name;
  1147.     /*    This is the DTE to use:
  1148.          *    EITHER ap->dte for forward
  1149.          *    OR     part of text for reverse
  1150.          */
  1151.     char    *dte = (m3p) ? m3p->m3_dte  : ap->dte;
  1152.     char    *ybts= (m3p) ? m3p->m3_ybts : ap->ybts;
  1153.     int    context = (m3p) ? m3p->m3_context : ap->context;
  1154.     int    network = (m3p) ? m3p->m3_network : ap->network;
  1155.     char    no_ybts = ybts == NULL || !strcmp(ybts, "");
  1156.  
  1157.     if (m3p && ! dte)
  1158.     { dte=nullstring; if (context == MAIL_NIFTP) return void_result; }
  1159.  
  1160.     {    char * net = vlookup(network, netnames);
  1161.         char *cont = vlookup(context, exp_21services);
  1162.  
  1163.         if (!net)
  1164.         {    warn2(1, "%10s: net 0x%02x unknown",
  1165.                 name, network);
  1166.             net = "??";
  1167.         }
  1168.         if (!cont)
  1169.         {    warn2(1, "%10s: context 0x%02x unknown",
  1170.                 name, context);
  1171.             cont = "??";
  1172.         }
  1173.         printf("0:%s:%s:", net, cont, name);
  1174.     }
  1175. /*    <isunix>:<network>:<service>:<name>:<addr>:<comment>    */
  1176.     if(stripoff && lexequ(stripoff, name, strlen(stripoff)) )
  1177.         printf("%s:", name + strlen(stripoff));
  1178.     else
  1179.         printf("%s:", name);
  1180.  
  1181.     /*    Prefix with gateway if needed  .... */
  1182.     if(network == PSS   && pssgateway )    printf("%s", pssgateway);
  1183.     if(network == JANET && janetgateway)    printf("%s", janetgateway);
  1184.  
  1185.     /*    The DTE ....    */
  1186.     printf("%s", dte);
  1187.     if (!no_ybts)    printf("/%s", ybts);
  1188.     printf(":");
  1189.  
  1190.     /*    The comment        */
  1191.     printf("\n");
  1192.  
  1193.     if (ap && ap->dte && dte != ap->dte && strcmp(dte, ap->dte))
  1194.         warn3(1, "%-18s DTE is %-14s rather than %-14s",
  1195.             name, dte, ap->dte);
  1196.     return void_result;
  1197. }
  1198.  
  1199. static_f void_res
  1200. york_21single(m2p, m3p, m4p)
  1201. Mod2    *m2p;
  1202. Mod3    *m3p;
  1203. Mod4    *m4p;
  1204. {    int j;
  1205.     int x29 = -1;    /* the quad which contains the x29 service if any */
  1206.     Atomic    *ap;
  1207.     char dte[15];
  1208.  
  1209.     VOID strcpy(dte, "<no x29 service>");    /* will not match */
  1210.  
  1211.     /* Let's see if we can find an X29 service.
  1212.      * If so, output it first & remember the DTE.
  1213.      * Then we may be able to omit later duplicates ....
  1214.      *
  1215.      * Also: If no X29, but there IS a TS29, THEN ....
  1216.      *       you could be clever & generate T entry (-> F & M)
  1217.      *     Any volunteers ??        (pb@cl.cam.ac.uk)
  1218.      */
  1219.     if (!m3p && cont_want[X29]) for( j = 0; j < m4p->nquads; j++)
  1220.         if (m4p->quads[j].fnumb <= max_fnumb)
  1221.         {    Table *tp = gettab(m4p->quads[j].fnumb);
  1222.         if (!tp || tp->T_context != X29)    continue;
  1223.         if(( ap = getatrec(&(m4p->quads[j]), m2p)) == NULL)
  1224.             continue;
  1225.  
  1226.         VOID strcpy(dte, ap->dte);
  1227.         york_21format(m2p, ap, m3p);
  1228.         x29 = j;
  1229.         break;
  1230.         }
  1231.  
  1232.     for( j = 0; j < m4p->nquads; j++) if (m4p->quads[j].fnumb <= max_fnumb)
  1233.     {    int    process_this_one = 0;
  1234.  
  1235.         if (j == x29)    continue;    /* Already done x29 */
  1236.  
  1237.         if(( ap = getatrec(&(m4p->quads[j]), m2p)) == NULL)
  1238.             continue;
  1239.         if(m3p && (ap-> context != m3p->m3_context ||
  1240.             ap->network != m3p->m3_network))
  1241.             continue;
  1242.         if (strcmp(dte, ap->dte)) process_this_one++;
  1243.         else
  1244.         {    char *expected_ybts=vlookup(ap->context,def_ybstring);
  1245.             char *given_ybts   = ap->ybts;
  1246.  
  1247.             if (!expected_ybts)    expected_ybts = "";
  1248.             if (!given_ybts)    given_ybts = "";
  1249.             if (strcmp(given_ybts, expected_ybts))
  1250.                 process_this_one++;
  1251.         }
  1252.         if (process_this_one)
  1253.             york_21format(m2p, ap, m3p);
  1254.     }
  1255.     return 1;
  1256. }
  1257.  
  1258. void_res
  1259. york21m4rec(m4p, shortname, longname, m3p)
  1260. Mod4    *m4p;
  1261. Mod3    *m3p;
  1262. Mod2    *shortname;
  1263. Mod2    *longname;
  1264. {
  1265.     static    headed    = 0;
  1266.  
  1267.     if( headed == 0 && commentfile)
  1268.     {
  1269.         addcomments(stdout, (m3p) ?
  1270.                 "york 2.1 format reverse NRS table" :
  1271.                 "york 2.1 format NRS table",
  1272.                 "Lookup Table");
  1273.         headed++;
  1274.     }
  1275.  
  1276.     if (!m4p || m3p)    return 0;
  1277.  
  1278.     if (shortname) {
  1279.         if (!york_21single(shortname, m3p, m4p))    return 0;
  1280.         if(!lexequ(shortname->name, longname->name, strlen(longname->name)))
  1281.             if (!york_21single(longname, m3p, m4p)) return 0;
  1282.     }
  1283.     else    if (!york_21single(longname, m3p, m4p)) return 0;
  1284.     return 1;
  1285. }
  1286.  
  1287. # endif F_YORK21
  1288.  
  1289. # ifdef    F_DBM1
  1290. /* ARGSUSED */
  1291. void_res
  1292. dbm1_single(n_quad, m4p)
  1293. int n_quad;
  1294. Mod4 *m4p;
  1295. {    FILE *fp;
  1296.     int i;
  1297.     FILE *locaterec();
  1298.     Quad *qp;
  1299.  
  1300.     if (n_quad >= 0 && (fp=locaterec(qp = &(m4p->quads[n_quad]))))
  1301.     {
  1302.         for( i = 1; i <= qp->nlines; i++)
  1303.         {    int len;
  1304.             char    string[MAXNAMELEN];
  1305.             char    tag[TAGSIZE];
  1306.  
  1307.             getstr(fp, tag, 0, 4);    /* the tag field */
  1308.             for (len=4; tag[len-1] == ' '; len--);
  1309.             tag[len] = '\0';
  1310.             len = getint(fp, 5);    /* length of next field */
  1311.             getstr(fp, string, 0, len);
  1312.             printf("%s%s %s", (i>1) ? "\r" : "", tag, string);
  1313.         }
  1314.     }
  1315.     printf("%c", DBSEP);
  1316.     return void_result;
  1317. }
  1318.  
  1319. #define    NEWS        DESC+1
  1320. #define    MAXDBM1CONTEXTS    DESC+2
  1321. #define    MAXNETWORKS    (JANET+1)
  1322.  
  1323. int context_interested[] = { TS29, X29, NIFTP, MAIL_NIFTP, JTMP, NEWS, DESC };
  1324. int net_interested[] = { JANET, PSS };
  1325.  
  1326. void_res
  1327. dbm1m4rec(m4p, shortname, longname, m3p)
  1328. Mod4    *m4p;
  1329. Mod3    *m3p;
  1330. Mod2    *shortname;
  1331. Mod2    *longname;
  1332. {    register i, j;
  1333.     int nets = 0;
  1334.     Mod2    *mainname;
  1335.     Mod2    *othername;
  1336.     int where[MAXDBM1CONTEXTS][MAXNETWORKS];
  1337.     int got[MAXNETWORKS];
  1338.     register Table *tp;
  1339.     static long t_time = 0;
  1340.     static count = 0;
  1341.  
  1342.     if (m3p || !m4p) return 0;
  1343.  
  1344.     if (t_time == 0) time(&t_time);
  1345.  
  1346.     /* Initialise the tables .. */
  1347.     for (j=0; j<MAXNETWORKS; j++)
  1348.     {    got[j] = 0;
  1349.         for (i=0; i<MAXDBM1CONTEXTS; i++) where[i][j] = -1;
  1350.     }
  1351.     
  1352.     /* Fill in what we have */
  1353.     for(j = 0; j < m4p->nquads; j++)
  1354.         if (m4p->quads[j].fnumb <= max_fnumb &&
  1355.             (tp = gettab(m4p->quads[j].fnumb)) &&
  1356.             tp->T_context < MAXDBM1CONTEXTS &&
  1357.             tp->T_network < MAXNETWORKS)
  1358.             where[tp->T_context][tp->T_network] = j;
  1359.  
  1360.     for (i=0; i < sizeof net_interested / sizeof net_interested[0]; i++)
  1361.     {    int net = net_interested[i];
  1362.         for(j = 0;
  1363.         j < sizeof context_interested / sizeof context_interested[0];
  1364.             j++)
  1365.             if(where[context_interested[j]][net] >= 0) got[net]++;
  1366.     }
  1367.  
  1368.     /* Count the number of nets */
  1369.     for (j=0; j<MAXNETWORKS; j++) if (got[j]) nets++;
  1370.  
  1371.     if (!shortname) shortname=longname;
  1372.  
  1373.     if (longshort == LONG)    mainname = longname , othername = shortname;
  1374.     else            mainname = shortname, othername = longname;
  1375.  
  1376.     printf("%c##%d %s\n", R_ALIAS, count, mainname->name);
  1377.     if (strcmp(mainname->name, othername->name))
  1378.         printf("%c%s %s\n", R_ALIAS, mainname->name, othername->name);
  1379.     printf("%c%s %s %d %d %d %d %d %d",
  1380.             R_MAIN, othername->name, mainname->name,
  1381.             t_time, count++, DEF_LOCAL, DEF_OLD, DEF_DISABLED,
  1382.             nets);
  1383.     
  1384.     /* Print info for nets that have some info */
  1385.     for (i=0; i < (sizeof net_interested / sizeof net_interested[0]); i++)
  1386.         if (got[net_interested[i]])
  1387.         {    int net = net_interested[i];
  1388.         char *netname = vlookup(net, lc_netnames);
  1389.  
  1390. #define    printgw(m4p, off) printf(" %d", (off<0) ? 0 : m4p->quads[off].ngtwys)
  1391.         /* Net name and some gateways */
  1392.         printf(" %d", DEF_MAXFTP);
  1393.         printgw(m4p, where[NIFTP][net]);
  1394.         printgw(m4p, where[MAIL_NIFTP][net]);
  1395.         printgw(m4p, where[JTMP][net]);
  1396.         printf(" %d", 0);    /* newsgates */
  1397.         printf(" %s%c", netname, DBSEP);
  1398.  
  1399.         /* Now the quads themselves */
  1400.         for(j = 0;
  1401.         j < (sizeof context_interested / sizeof context_interested[0])-1;
  1402.             j++)
  1403.             dbm1_single(where[context_interested[j]][net], m4p);
  1404.         }
  1405.     dbm1_single(where[DESC][JANET], m4p);
  1406.     printf("\n");
  1407.     return 1;
  1408. }
  1409.  
  1410. /* ARGSUSED */
  1411. void_res
  1412. dbm1format(longname, shortname, ap, m3p)
  1413. Mod2    *longname, *shortname;
  1414. Atomic    *ap;
  1415. Mod3    *m3p;
  1416. {    Mod2 *mainname = shortname;
  1417.  
  1418.  
  1419.     if (!m3p)
  1420.     {    warn0(1, "DBM1 single passed forward object");
  1421.         return void_result;
  1422.     }
  1423.  
  1424.     if (!mainname || longshort == LONG) mainname = longname;
  1425.  
  1426.     if (mixlow != MIXED) VOID lowerfy(m3p->m3_string); /* true .. */
  1427.     printf("%c%c %s %s\n", R_REV, m3p->m3_context + '0',
  1428.         mainname->name, m3p->m3_string);    /* UGH !! */
  1429.  
  1430.     return void_result;
  1431. }
  1432.  
  1433. void_res
  1434. dbm1domain(dp)
  1435. Domain    *dp;
  1436. {
  1437.     printf("%c%s %s\n", R_DOMAIN, dp->name, dp->gateway); /* UGH !! */
  1438.  
  1439.     return void_result;
  1440. }
  1441. # endif    F_DBM1
  1442.  
  1443. #ifdef F_PRIME
  1444. void_res
  1445. primeformat(longname, shortname, ap, m3p)
  1446. Mod2   *longname, *shortname;
  1447. Atomic *ap;
  1448. Mod3   *m3p;
  1449. {
  1450.     int i;
  1451.  
  1452.     if (m3p) printf("Calling_Address: %s\n", m3p -> m3_string);
  1453.  
  1454.     printf("Standard_Name: %s\n", longname -> name);
  1455.  
  1456.     printf("Abbreviated_Name: %s\n", 
  1457.             (shortname) ? shortname -> name : longname -> name);
  1458.  
  1459.     if (m3p)
  1460.     {    if (m3p->m3_dte) printf("DTE_String: %s\n", m3p->m3_dte);
  1461.         if (*(m3p->m3_ybts)) printf("YBTS_String: %s\n",m3p->m3_ybts);
  1462.         if (ap) for (i = 0; i < ap->n_descs; i++)
  1463.                 printf("Description: %s\n", ap->desc[i]);
  1464.     }
  1465.     else
  1466.     {    if (ap->dte  && *ap->dte)
  1467.                 printf("DTE_String: %s\n", ap->dte);
  1468.         if (ap->ybts && *ap->ybts)
  1469.                 printf("YBTS_String: %s\n", ap->ybts);
  1470.  
  1471.         for (i = 0; i < ap->n_relays; i++)
  1472.             printf("Application_Relay: %s\n", ap->ar[i]);
  1473.         for (i = 0; i < ap->n_descs; i++)
  1474.             printf("Description: %s\n", ap->desc[i]);
  1475.     }
  1476.  
  1477.     printf("\n");
  1478.  
  1479.     return void_result;
  1480. }
  1481.  
  1482. void_res
  1483. primedomain(dp)
  1484. Domain    *dp;
  1485. {
  1486.     printf("domain: %s",dp->name);
  1487.     printf(" -gate %s\n",dp->gateway);
  1488.     return void_result;
  1489. }
  1490.  
  1491. #endif F_PRIME
  1492.  
  1493. # ifdef    F_EDTEXT
  1494. /*
  1495.  * Go through all the quads associated with this name (s). This will
  1496.  * lead us to all the forward, reverse, and description info (I hope!).
  1497.  * call edtextformat() with appropriate args to make it do the Right Thing.
  1498.  */
  1499. void_res
  1500. edtextm4rec(m4p, shortname, longname, m3p)
  1501. Mod4    *m4p;
  1502. Mod3    *m3p;
  1503. Mod2    *shortname;
  1504. Mod2    *longname;
  1505. {
  1506.     int i, j;
  1507.     Atomic    *ap, fakeap;
  1508.     Mod3 *mm3p;
  1509.     Table *tp;
  1510.     static    headed    = 0;
  1511.     static    partial    = 0;
  1512.     char    *prefix1 = (options & O_ED_SHORT) ?
  1513.              (shortname) ? shortname->name : longname->name :
  1514.              (char *) 0;
  1515.     char    *prefix2 = (options & O_ED_LONG) ? longname->name :
  1516.              (char *) 0;
  1517.  
  1518.     if (!m4p || m3p)
  1519.     {    warn1(1, "EDTEXT passed reverse object (%s)",
  1520.             (m3p) ? "m3p" : "!m4p");
  1521.         return 1;
  1522.     }
  1523.  
  1524.     if( headed == 0 && commentfile)
  1525.     {    char * type;
  1526.         switch (options & O_ED_MASK)
  1527.         {
  1528.         case O_ED_SIMPLE:    type = "simple format";        break;
  1529.         case O_ED_SHORT:    type = "short format";        break;
  1530.         case O_ED_LONG:        type = "long format";        break;
  1531.         case O_ED_LONG|O_ED_SHORT: type = "long & short format";break;
  1532.         default:        type = "unknown format";    break;
  1533.         }
  1534.         addcomments(stdout, "Edinburgh text format NRS table", type);
  1535.         headed++;
  1536.     }
  1537.  
  1538.  
  1539.     /* print out the name(s) if needed*/
  1540.     if (!(prefix1 && prefix2))
  1541.     {    
  1542.         if (!prefix2)
  1543.         {    if (prefix1)    printf("%-*s ", FL_PREF1, prefix1);
  1544.             printf("%-*s %s\n", FL_CNTX, "SN", longname->name);
  1545.         }
  1546.         if (shortname && !prefix1)
  1547.         {    if (prefix2)    printf("%-*s ", FL_PREF2, prefix2);
  1548.              printf("%-*s %s\n", FL_CNTX, "AN", shortname->name);
  1549.         }
  1550.     }
  1551.  
  1552.     /* print out the DESC info at the top ... */
  1553.     for( j = 0; j < m4p->nquads; j++)
  1554.         if (m4p->quads[j].fnumb==trip2fnumb[DESC][JANET][DIR_FORWARDS] &&
  1555.         (ap = getatrec(&(m4p->quads[j]), 
  1556.             (shortname) ? shortname : longname)))
  1557.             edtextformat(longname, ap, NULL, prefix1, prefix2);
  1558.  
  1559.     /* ... then print out the rest */
  1560.     for( j = 0; j < m4p->nquads; j++)
  1561.     {
  1562.         if ((m4p->quads[j]).fnumb ==
  1563.             trip2fnumb[DESC][JANET][DIR_FORWARDS]) continue;
  1564.  
  1565.         /* forward lookup? */
  1566.         if ((m4p->quads[j]).fnumb <= max_fnumb &&
  1567.              (ap = getatrec(&(m4p->quads[j]),
  1568.             (shortname) ? shortname : longname)))
  1569.             mm3p = NULL;
  1570.         else if ((m4p->quads[j]).fnumb > fnumb)
  1571.         /* reverse lookup. groan - magic numbers */
  1572.         {    if (partial && !gettab((m4p->quads[j]).fnumb - max_fnumb))
  1573.                 continue;
  1574.             if (!(mm3p = getm3rec((m4p->quads[j]).disp)))
  1575.             {    warn3(0,
  1576.                     "getm3rec problem on %s line %d of %d",
  1577.                     longname->name, m4p->quads[j].disp,
  1578.                     m4p->quads[j].fnumb);
  1579.                 continue;
  1580.             }
  1581.             ap = (Atomic *) 0; /* Keep gcc -Wall happy */
  1582.         }
  1583.         else if ((i = (m4p->quads[j]).fnumb) ==
  1584.                 trip2fnumb[JTMP_FILES][JANET][DIR_FORWARDS] ||
  1585.             i ==    trip2fnumb[JTMP_REG  ][JANET][DIR_FORWARDS])
  1586.         /*
  1587.          * These contexts do not appear to have any
  1588.          * attached info. So we fake up a record to hand
  1589.          * to edtextformat().
  1590.          * There are the ones I came across; there are probably
  1591.          * others that will need the same treatment if they ever
  1592.          * do appear in the nrs.
  1593.          * It would help if I understood what these contexts
  1594.          * meant! What is YBTS-NODE?? MAIL-X29?? My aching brain...
  1595.          */
  1596.         {    tp = gettab((m4p->quads[j]).fnumb);
  1597.             bzero(&fakeap, sizeof fakeap);
  1598.             if (!tp)
  1599.             {    if (!partial)
  1600.                 {    Quad *x = &(m4p->quads[j]);
  1601.                     warn1(0,
  1602.                 "context not included in .cf file for %s",
  1603.                         longname->name);
  1604.                     warn3(0,
  1605.                 "Context %d, subnetwork %d, direction %d",
  1606.                         fnumb2trip[x->fnumb].f_cont,
  1607.                         fnumb2trip[x->fnumb].f_subn,
  1608.                         fnumb2trip[x->fnumb].f_dirn);
  1609.                     warn3(0, "[ fnumb=%d, disp=%d, nlines=%d ]\n",
  1610.                         x->fnumb, x->disp, x->nlines);
  1611.                     partial++;
  1612.                 }
  1613.                 continue;
  1614.             }
  1615.             fakeap.context = tp->T_context;
  1616.             fakeap.network = tp->T_network;
  1617.             ap = &fakeap;
  1618.             mm3p = NULL;
  1619.         }
  1620.         else
  1621.         /*
  1622.          * HELP!!!
  1623.          * If it ever gets here then I don't understand what is
  1624.          * going on. But I will at least let the user know...
  1625.          */
  1626.         {    tp = gettab((m4p->quads[j]).fnumb);
  1627.             if (!partial || tp)
  1628.             {    Quad *x = &(m4p->quads[j]);
  1629.                 if (!tp) warn3(0,
  1630.                 "context %s in %s not included in .cf file for %s",
  1631.                 vlookup(fnumb2trip[x->fnumb].f_cont, contexts),
  1632.                 vlookup(fnumb2trip[x->fnumb].f_subn, netnames),
  1633.                         longname->name);
  1634.                 warn3(0,
  1635.                 "Context %d, subnetwork %d, direction %d",
  1636.                         fnumb2trip[x->fnumb].f_cont,
  1637.                         fnumb2trip[x->fnumb].f_subn,
  1638.                         fnumb2trip[x->fnumb].f_dirn);
  1639.                 warn3(0, "[ fnumb=%d, disp=%d, nlines=%d ]\n",
  1640.                     x->fnumb, x->disp, x->nlines);
  1641.                 if (!tp)partial++;
  1642.             }
  1643.             continue;
  1644.         }
  1645.         edtextformat(longname, ap, mm3p, prefix1, prefix2);
  1646.     }
  1647.  
  1648.     printf("\n");
  1649.     return(1);    /* OK -- we did it ! */
  1650. }
  1651.  
  1652.  
  1653.  
  1654. /*
  1655.  * print the stuff out. If m3p is non null we are printing out a
  1656.  * reverse entry. I am sure this could be cleaner.
  1657.  */
  1658. void_res
  1659. edtextformat(m2p, ap, m3p, prefix1, prefix2)
  1660. Mod2    *m2p;
  1661. Atomic    *ap;
  1662. Mod3    *m3p;
  1663. char    *prefix1;
  1664. char    *prefix2;
  1665. {    int context    = (m3p) ? m3p->m3_context : ap->context;
  1666.     int network    = (m3p) ? m3p->m3_network : ap->network;
  1667.     char *cont    = vlookup(context, contexts);
  1668.     char *net    = vlookup(network, netabbrevs);
  1669.     char *name    = m2p->name;
  1670.     if (!cont)
  1671.     {    warn2(1, "%10s: context 0x%02x unknown", name, context);
  1672.         cont = "??";
  1673.     }
  1674.     if (!net)
  1675.     {    warn2(1, "%10s: net 0x%02x unknown", name, network);
  1676.         net = "??";
  1677.     }
  1678.  
  1679.     if (context == DESC)
  1680.     {    /* If m3p then we already done it */
  1681.         if (prefix1)    printf("%-*s ", FL_PREF1, prefix1);
  1682.         if (prefix2)    printf("%-*s ", FL_PREF2, prefix2);
  1683.         if( !m3p && ap->n_descs > 0 )
  1684.         {    int desc;
  1685.             printf("%-*s ", FL_CNTX, "DI");
  1686.             for (desc=0; desc < ap->n_descs; desc++)
  1687.                 printf("%s%s", (desc==0) ? "" : " ", ap->desc[desc]);
  1688.         }
  1689.         printf("\n");
  1690.         return(0);
  1691.     }
  1692.  
  1693.     /*
  1694.      * you can tell this is a hack by the number of times
  1695.      * I go `if (m3p)'...
  1696.      */
  1697.     /*
  1698.      * Special cases... perhaps more contexts belong here too.
  1699.      */
  1700.     if (prefix1)    printf("%-*s ", FL_PREF1, prefix1);
  1701.     if (prefix2)    printf("%-*s ", FL_PREF2, prefix2);
  1702.  
  1703.     if (m3p)   /* Reverse entry */
  1704.         printf("%-*s %-*s R CA %s",
  1705.                 FL_CNTX, cont, FL_NET, net, m3p->m3_string);
  1706.     else       /* forward entry... DI caught above */
  1707.     {    char    *dte    = ap->dte;
  1708.         char    *ybts    = ap->ybts;
  1709.         char    no_ybts = ybts == NULL || !strcmp(ybts, "");
  1710.     
  1711.         if (! dte) dte = "";
  1712.  
  1713.         if (context == JTMP_FILES || context == JTMP_REG)
  1714.             printf("%-*s %-*s", FL_CNTX, cont, FL_NET, net);
  1715.         else
  1716.             printf("%-*s %-*s F DT %s", FL_CNTX, cont, FL_NET, net, dte);
  1717.         if( ! no_ybts )
  1718.             printf(" YB %s", ybts);
  1719.  
  1720.         if( ap->n_relays > 0 )
  1721.         {    int relay;
  1722.             printf(" AR ");
  1723.             for (relay=0; relay < ap->n_relays; relay++)
  1724.                 printf("%s%s", (relay) ? "; " : "",
  1725.                     ap->ar[relay]);
  1726.         }
  1727.     }
  1728.  
  1729.     printf("\n");
  1730.  
  1731.     return(0);
  1732. }
  1733.  
  1734. void_res
  1735. edtextdomain(dp)
  1736. Domain    *dp;
  1737. {    printf("%-*s %-*s %s\n", FL_CNTX, "DM", FL_DOM, dp->name, dp->gateway);
  1738.     return void_result;
  1739. }
  1740. # endif    F_EDTEXT
  1741.  
  1742. # ifdef    F_VME
  1743. char *
  1744. vmehash(data)
  1745. char *data;
  1746. {    int val;
  1747.     static char res[3];
  1748.     static char table[] =
  1749.          "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  1750.  
  1751.     for (val=0; *data; data++) val = val + *data;
  1752.  
  1753.     res[0] = table[val % (sizeof table -1)];
  1754.     res[1] = table[(val / (sizeof table -1)) % (sizeof table -1)];
  1755.  
  1756.     res[sizeof res -1] = '\0';
  1757.     return res;
  1758. }
  1759.  
  1760. static_f void
  1761. vmecompress(to, from)
  1762. char *from, *to;
  1763. {
  1764.     register char * p;
  1765.     if (!strncmp(from, VME_STRIP, sizeof(VME_STRIP) -1))
  1766.         from += sizeof(VME_STRIP) -1;
  1767.  
  1768.     for(p=to; *from; from++) if (*from != '.') *to++ = *from;
  1769.     *to = '\0';
  1770. }
  1771.  
  1772. static_f void
  1773. vmeout(lftf, nrsa, nrsb, roucn)
  1774. char *lftf, *nrsa, *nrsb, *roucn;
  1775. {    printf("%-*.*s", VME_HFTFLEN, VME_HFTFLEN, vmehash(lftf));
  1776.     printf("%-*.*s", VME_HNRSALEN, VME_HNRSALEN, vmehash(nrsa));
  1777.     printf("%-*.*s", VME_HNRSBLEN, VME_HNRSBLEN, (nrsb)?vmehash(nrsb):"");
  1778.     printf("%-*d", VME_SERCNLEN, VME_SERCN_RELAY);
  1779.     printf("%-*d", VME_PROPCNLEN, VME_PROPCN_ROUTE);
  1780.     printf("%-*s", VME_MAILSRLEN, "");
  1781.     printf("%-*s", VME_LFTFLEN, lftf);
  1782.     printf("%-*s", VME_NRSALEN, nrsa);
  1783.     printf("%-*s", VME_NRSBLEN, (nrsb) ? nrsb : "");
  1784.     printf("%-*.*s", VME_ROUCNLEN, VME_ROUCNLEN, roucn);
  1785.     printf("\n");
  1786. }
  1787.  
  1788. /* ARGSUSED */
  1789. void_res
  1790. vmeformat(longform, shortform, ap, m3p)    /* vme domain table format */
  1791. Mod2    *longform;
  1792. Mod2    *shortform;
  1793. Atomic    *ap;
  1794. Mod3    *m3p;
  1795. {    char    compressed[VME_LFTFLEN+1];
  1796.     static    headed    = 0;
  1797.  
  1798.     if (!ap)
  1799.     {    warn0(1, "VME passed reverse object");
  1800.         return void_result;
  1801.     }
  1802.  
  1803.     if (!shortform)
  1804.     {    warn1(1, "VME passed %s without shortform", longform->name);
  1805.         return void_result;
  1806.     }
  1807.  
  1808.     if( headed == 0 && commentfile)
  1809.     {    addcomments(stdout, "VME format NRS", "Mail table");
  1810.         headed++;
  1811.     }
  1812.  
  1813.     vmecompress(compressed, shortform->name);
  1814.     vmeout(compressed, shortform->name, longform->name, "NOTICF");
  1815.  
  1816.     return    void_result;
  1817. }
  1818.  
  1819. int
  1820. vmem4rec(m4p, shortname, longname, m3p)
  1821. Mod4    *m4p;
  1822. Mod3    *m3p;
  1823. Mod2    *shortname;
  1824. Mod2    *longname;
  1825. {
  1826.     int j;
  1827.     Atomic    *ap;
  1828.  
  1829.     if (!m4p || m3p)
  1830.     {    warn1(1, "VME passed reverse object (%s)",
  1831.             (m3p) ? "m3p" : "!m3p");
  1832.         return 1;
  1833.     }
  1834.  
  1835.     for( j = 0; j < m4p->nquads; j++)
  1836.         if ((m4p->quads[j]).fnumb <= max_fnumb &&
  1837.          (ap = getatrec(&(m4p->quads[j]),
  1838.             (shortname) ? shortname : longname)))
  1839.         {    vmeformat(longname, shortname, ap, NULL);
  1840.         /* If JANET and PSS, only output one of them */
  1841.         break;
  1842.         }
  1843.  
  1844.     return(1);    /* OK -- we did it ! */
  1845. }
  1846.  
  1847. void_res
  1848. vmedomain(dp)
  1849. Domain    *dp;
  1850. {    char    compressed[VME_LFTFLEN+1];
  1851.     char    compress2[VME_LFTFLEN+1];
  1852.  
  1853.     vmecompress(compressed, dp->name);
  1854.     vmecompress(compress2, dp->gateway);
  1855.     vmeout(dp->name, compressed, 0, compress2);
  1856.  
  1857.     return void_result;
  1858. }
  1859. # endif    F_VME
  1860.  
  1861. # ifdef    F_PP
  1862. static_f void
  1863. pp_domain(hostname, stdname, file)
  1864. Mod2    *hostname, *stdname;
  1865. FILE    *file;
  1866. {    fprintf(file, "%s:", flip(hostname->name));
  1867.     fprintf(file, "%s\n", flip(stdname->name));
  1868. }
  1869.  
  1870. static_f int
  1871. pp_channel(hostname, m4p, file)
  1872. Mod2    *hostname;
  1873. Mod4    *m4p;
  1874. FILE    *file;
  1875. {    Atomic    *ap;
  1876.     int j;
  1877.     char buff[4096];
  1878.     char *ptrs[10];
  1879.     int done_janet = 0;
  1880.     int done_pss = 0;
  1881.     int done = 0;
  1882.     int i;
  1883.  
  1884.     ptrs[0] = buff;
  1885.  
  1886.     for( j = 0; j < m4p->nquads; j++)
  1887.     {
  1888.         if ((m4p->quads[j]).fnumb ==
  1889.             trip2fnumb[MAIL_NIFTP][JANET][DIR_FORWARDS])
  1890.         {    if (done_janet++)    continue;
  1891.         }
  1892.         else if ((m4p->quads[j]).fnumb ==
  1893.             trip2fnumb[MAIL_NIFTP][PSS][DIR_FORWARDS])
  1894.         {    if (done_pss++)        continue;
  1895.         }
  1896.         else    continue;
  1897.  
  1898.         /* forward lookup? */
  1899.         if (ap = getatrec(&(m4p->quads[j]), hostname))
  1900.         {    if (ap->n_relays)
  1901.                 sprintf(ptrs[done], "%s()",
  1902.                     flip(longshort_name(ap->ar[0])));
  1903.             else    switch(ap->network) {
  1904.             case PSS:
  1905.                 sprintf(ptrs[done],
  1906.                     "%s(gb-%s)", flip(hostname->name),
  1907.                     lexequ(ap->dte, "2342", 4) ? "pss" :
  1908.                      "ipss");
  1909.                 break;
  1910.     
  1911.             case JANET:
  1912.                 sprintf(ptrs[done], "%s(gb-janet)",
  1913.                     flip(hostname->name));
  1914.                 break;
  1915.             }
  1916.             for (i=0; i<done; i++)
  1917.                 if (!strcmp(ptrs[i], ptrs[done])) break;
  1918.             if (i < done) continue;
  1919.             ptrs[done+1] = ptrs[done] + strlen(ptrs[done]) + 1;
  1920.             done++;
  1921.             }
  1922.     }
  1923.  
  1924.     if (!done) return 0;
  1925.  
  1926.     fprintf(file, "%s:", flip(hostname->name));
  1927.     for (i=0; i<done; i++) fprintf(file, "%s%s", (i==0) ? "":",", ptrs[i]);
  1928.     fprintf(file, "\n");
  1929.     return 1;
  1930. }
  1931.  
  1932. static    FILE    *dmnfile = (FILE *) 0;
  1933. static    FILE    *chanfile = (FILE *) 0;
  1934.  
  1935. void_res
  1936. ppm4rec(m4p, shortname, longname, m3p)
  1937. Mod4    *m4p;
  1938. Mod3    *m3p;
  1939. Mod2    *shortname;
  1940. Mod2    *longname;
  1941. {    Mod2    *stdform, *aliasform;
  1942.     static    int first = 1;
  1943.  
  1944.     if (m3p)
  1945.     {    warn0(1, "PP passed reverse object");
  1946.         return 1;
  1947.     }
  1948.  
  1949.     if (first)
  1950.     {    File_list    *filep;
  1951.  
  1952.         if(filep = findfile(fil_list, "-chan-...", 1))
  1953.             chanfile = getfp(filep->fname, "w");
  1954.         if (!chanfile) chanfile = stdout;
  1955.         if(commentfile) addcomments(chanfile, (m3p) ?
  1956.             "PP format reverse NRS table" :
  1957.             "PP format NRS table",
  1958.             "Lookup Table");
  1959.  
  1960.         if(filep = findfile(fil_list, "-dmn-...", 1))
  1961.             dmnfile = getfp(filep->fname, "w");
  1962.         if (!dmnfile) fprintf(stderr, "No dmn file\n");
  1963.         else if(commentfile) addcomments(dmnfile, (m3p) ?
  1964.             "PP format reverse NRS table" :
  1965.             "PP format NRS table",
  1966.             "Lookup Table");
  1967.         first = 0;
  1968.     }
  1969.  
  1970.     if (!shortname) shortname = longname;
  1971.  
  1972.     if( longshort == LONG )    /* output in short = alias of long */
  1973.         stdform = longname,  aliasform = shortname;
  1974.     else    stdform = shortname, aliasform = longname;
  1975.  
  1976.     if (!pp_channel(stdform, m4p, chanfile))    return 1;
  1977.  
  1978.     if (dmnfile)
  1979.     {    pp_domain(stdform, stdform, dmnfile);
  1980.         if (aliasform &&
  1981.         !lexequ(aliasform->name, stdform->name, strlen(longname->name)))
  1982.             pp_domain(aliasform, stdform, dmnfile);
  1983.     }
  1984.     return 1;
  1985. }
  1986.  
  1987. void_res
  1988. ppdomain(dp)
  1989. Domain    *dp;
  1990. {    
  1991.     FILE *fp;
  1992.  
  1993.     if (chanfile)
  1994.     {    fprintf(chanfile, "%s:",    flip(dp->name));
  1995.         fprintf(chanfile, "%s()\n", flip(longshort_name(dp->gateway)));
  1996.     }
  1997.     if (dmnfile)
  1998.     {    fprintf(dmnfile, "%s:",    flip(dp->name));
  1999.         fprintf(dmnfile, "%s *\n", flip(dp->name));
  2000.     }
  2001.     return void_result;
  2002. }
  2003. # endif    F_PP
  2004.